package com.sebscape.sebcms.setup.actions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.opensymphony.xwork2.ActionSupport;
import com.sebscape.sebcms.pages.domain.Page;
import com.sebscape.sebcms.pages.domain.SiteMapEntry;
import com.sebscape.sebcms.pages.persistence.PageDao;
import com.sebscape.sebcms.pages.persistence.SiteMapEntryDao;
import com.sebscape.sebcms.persistence.dao.GenericDao;
import com.sebscape.sebcms.security.domain.Group;
import com.sebscape.sebcms.security.domain.Role;
import com.sebscape.sebcms.security.domain.User;
import com.sebscape.sebcms.security.persistence.GroupDao;
import com.sebscape.sebcms.security.persistence.UserDao;
import com.sebscape.sebcms.setup.domain.SetupConfiguration;

public class SiteSetupActions extends ActionSupport {
	
	private static final long serialVersionUID = 3158641473609016405L;
	private Map<String,List<String>> results;
	private String message;
	private Map<String, Object> createdItems; //collect items so that they can be reused. 
											  // ie - need groups so we can assign them
											  // to users in later method.
	public String execute(){
		if( !isConfigured() ){
			// create a map which will store results for all setups. This is
			// so the landing page can reflect what users and pages, etc. are available.
			results = new HashMap<String,List<String>>();
			// init the createdItems Map.
			this.createdItems = new HashMap<String, Object>();
			// create config record
			results.put( "Site Config", setupConfig() );
			// create groups
			results.put( "Groups", setupGroups() );
			// create roles
			results.put( "Groups", setupRoles() );
			// create users (these can only be created after Roles and Groups)
			results.put( "Users", setupUsers() );
			// create pages
			results.put( "Groups", setupPages() );
			// done.
			this.message = "Completed.";
		} else {
			this.message = "System Already Configured";
		}
		return SUCCESS;
	}
	
	private Boolean isConfigured(){
		GenericDao<SetupConfiguration,Long> dao = new GenericDao<SetupConfiguration, Long>( SetupConfiguration.class );
		List<SetupConfiguration> list = dao.findAll();
		if( list != null && list.size() > 0 ){
			return Boolean.TRUE;
		} else {
			return Boolean.FALSE;
		}
	}
	
	private List<String> setupConfig(){
		try {
			SetupConfiguration config = new SetupConfiguration("sebCMS", "Default sebCMS Configuration",
					"contact me at: webmaster@mySite.com", "smtp.mysite.com", "admin@mysite.com",
					"smtpUsername", "smtpPassword", "[sebCMS notification] ", "The content of this email is confidential.",
					"MyWebsiteSlides", "picassaUsername", "picassaPassword","Welcome, $user.emailAddress!",
					"undefined TemplateLostPassword","undefined TemplateNotice");
			GenericDao<SetupConfiguration,Long> dao = new GenericDao<SetupConfiguration, Long>( SetupConfiguration.class );
			dao.save( config );
			return Arrays.asList( new String[]{ "SiteName: My Site", "Contact: webmaster@mysite.com" } );
		} catch (Exception e) {
			e.printStackTrace();
			return Arrays.asList( new String[]{ "FAILED", e.getCause().getMessage() } );
		}
	}

	private List<String> setupGroups(){
		try {
			Group admin = new Group( "System Administrators", "This group is required by the system - it cannot be modified or deleted.", "R");
			Group guest = new Group( "Anonymous", "This is the default group attributed to all guests. This group is required by the system - it cannot be modified or deleted.", "R");
			Group member = new Group( "Member", "A sample group for users who login to the site.");
			GroupDao dao = new GroupDao();
			createdItems.put( "admin", dao.save( admin ) );
			createdItems.put( "guest", dao.save( guest ) );
			createdItems.put( "member", dao.save( member ) );
			return Arrays.asList( new String[]{ "System Administrators", "Anonymous", "Member" } );
		} catch (Exception e) {
			e.printStackTrace();
			return Arrays.asList( new String[]{ "FAILED", e.getCause().getMessage() } );
		}
	}

	private List<String> setupRoles(){
		try {
			Role superuser = new Role( "superuser", "This role is required by the system - it cannot be modified or deleted.", "R");
			Role viewer = new Role( "viewer", "This role is required by the system - it cannot be modified or deleted.", "R");
			Role editor = new Role( "editor", "This is the default Role attributed to all guests. This Role is required by the system - it cannot be modified or deleted.", "R");
			GenericDao<Role, Long> dao = new GenericDao<Role, Long>( Role.class );
			createdItems.put( "superuser", dao.save( superuser ) );
			createdItems.put( "viewer", dao.save( viewer ) );
			createdItems.put( "editor", dao.save( editor ) );
			return Arrays.asList( new String[]{ "superuser", "viewer", "editor" } );
		} catch (Exception e) {
			e.printStackTrace();
			return Arrays.asList( new String[]{ "FAILED", e.getCause().getMessage() } );
		}
	}
	
	private List<String> setupUsers(){
		 /* @param name
		 * @param nickname
		 * @param password
		 * @param firstname
		 * @param lastname
		 * @param emailAddress
		*/
		try {
			User admin = new User( "admin", "System Administrator", "admin", "System", "Administrator", "admin@sebcms.com");
			admin.setGroupKeySet( new HashSet<Key>() );
			admin.getGroupKeySet().add( KeyFactory.createKey("Group", ( (Group)createdItems.get( "admin" ) ).getId() ) );
			admin.getGroupKeySet().add( KeyFactory.createKey("Group", ( (Group)createdItems.get( "guest" ) ).getId() ) );
			admin.setRoleKeySet( new HashSet<Key>() );
			admin.getRoleKeySet().add( KeyFactory.createKey("Role", ( (Role)createdItems.get( "superuser" ) ).getId() ) );
			
			User member = new User( "member", "Sample Member", "member", "Sample", "Member", "member@sebcms.com");
			member.setGroupKeySet( new HashSet<Key>() );
			member.getGroupKeySet().add( KeyFactory.createKey("Group", ( (Group)createdItems.get( "member" ) ).getId() ) );
			member.getGroupKeySet().add( KeyFactory.createKey("Group", ( (Group)createdItems.get( "guest" ) ).getId() ) );
			member.setRoleKeySet( new HashSet<Key>() );
			member.getRoleKeySet().add( KeyFactory.createKey("Role", ( (Role)createdItems.get( "viewer" ) ).getId() ) );
			
			User editor = new User( "editor", "Sample Editor", "editor", "Sample", "Editor", "editor@sebcms.com");
			editor.setGroupKeySet( new HashSet<Key>() );
			editor.getGroupKeySet().add( KeyFactory.createKey("Group", ( (Group)createdItems.get( "member" ) ).getId() ) );
			editor.getGroupKeySet().add( KeyFactory.createKey("Group", ( (Group)createdItems.get( "guest" ) ).getId() ) );
			editor.setRoleKeySet( new HashSet<Key>() );
			editor.getRoleKeySet().add( KeyFactory.createKey("Role", ( (Role)createdItems.get( "viewer" ) ).getId() ) );
			editor.getRoleKeySet().add( KeyFactory.createKey("Role", ( (Role)createdItems.get( "editor" ) ).getId() ) );

			UserDao dao = new UserDao();
			dao.save( admin );
			dao.save( editor );
			dao.save( member );
			return Arrays.asList( new String[]{ "Logins (username/password):", 
					"admin / admin",
					"member / member",
					"editor / editor"} );
		} catch (Exception e) {
			e.printStackTrace();
			return Arrays.asList( new String[]{ "FAILED", e.getCause().getMessage() } );
		}
	}
	
	private List<String> setupPages(){
		try {
			// home page
			Page home = new Page( "Home", "Installation Home Page", "/", HOME_PAGE );
			home.setIsPublic( Boolean.TRUE );
			// Members Home
			Page members = new Page( "Member Home", "Installation Members-Home Page", "/members/home", "<i>Add Your Content Here</i>");
			members.setIsPublic( Boolean.FALSE );
			members.setGroups( Arrays.asList( new Group[]{
					(Group)createdItems.get( "member" ),
					(Group)createdItems.get( "admin" )
			} ) );
			// Admin Home
			Page admins = new Page( "Admin Home", "Administration Page", "/admin/home", "<i>Add Your Content Here</i>");
			admins.setIsPublic( Boolean.FALSE );
			admins.setGroups( Arrays.asList( new Group[]{
					(Group)createdItems.get( "admin" )
			} ) );
			PageDao dao = new PageDao();
			dao.save( home );
			dao.save( members );
			dao.save( admins );
			// add pages to siteMap.
			SiteMapEntryDao smDao = new SiteMapEntryDao();
			SiteMapEntry root = smDao.save( new SiteMapEntry( home, (Key)null ) );
			SiteMapEntry smeMembers = smDao.save( new SiteMapEntry( members, root ) );
			SiteMapEntry smeAdmin = smDao.save( new SiteMapEntry( admins, root ) );
			
			root.setChildSiteMapEntryKeyList( new ArrayList<Key>() );
			root.getChildSiteMapEntryKeyList()
				.add( KeyFactory.createKey("SiteMapEntry", smeMembers.getId() ) );
			root.getChildSiteMapEntryKeyList()
				.add( KeyFactory.createKey("SiteMapEntry", smeAdmin.getId() ) );
			
			smDao.update( root );
			return Arrays.asList( new String[]{ "Pages (name: customUrl):", 
					"Home: /",
					"Member Home: /members/home",
					"Admin Home: /admin/home"} );
		} catch (Exception e) {
			e.printStackTrace();
			return Arrays.asList( new String[]{ "FAILED", e.getCause().getMessage() } );
		}
	}

	//////////////////////////////////
	// Getters and Setters
	//////////////////////////////////
	
	/**
	 * @return the results
	 */
	public Map<String, List<String>> getResults() {
		return results;
	}

	/**
	 * @param results the results to set
	 */
	public void setResults(Map<String, List<String>> results) {
		this.results = results;
	}

	/**
	 * @return the createdItems
	 */
	public Map<String, Object> getCreatedItems() {
		return createdItems;
	}

	/**
	 * @param createdItems the createdItems to set
	 */
	public void setCreatedItems(Map<String, Object> createdItems) {
		this.createdItems = createdItems;
	}
	
	/**
	 * @return the message
	 */
	public String getMessage() {
		return message;
	}

	/**
	 * @param message the message to set
	 */
	public void setMessage(String message) {
		this.message = message;
	}

	private static final String HOME_PAGE = "<p><strong><span style=\"font-size: medium;\">Welcome to <span style=\"font-size: x-large;\"><span style=\"color: #008000;\">seb</span><span style=\"color: #0000ff;\">CMS</span></span>. </span></strong></p>"
		+"<p><span style=\"font-size: small;\">This site is home to the sevCMS Content Management Sytem. This is NOT software endorsed or provided by Google App Engine - but it is software intended specifically for their service.</span></p>"
		+"<p>&nbsp;</p>"
		+"<p><span style=\"font-size: small;\">At this time the CMS only supports these minimal operations:</span></p>"
		+"<ul>"
		+"<li><span style=\"font-size: small;\">Creation of Security Groups.</span></li>"
		+"<li><span style=\"font-size: small;\">Administrators can create user accounts. and assign them to groups.<br /></span></li>"
		+"<li><span style=\"font-size: small;\">Administrators can create and edit pages.</span></li>"
		+"<li><span style=\"font-size: small;\">The backend has been created for login processing and protection of secured pages. This is currently disabled so I can be sure to access all pages and functions while I am still developing.</span></li>"
		+"<li><span style=\"font-size: small;\">A slideshow widget which gathers images(urls) from Google Picasa.</span></li>"
		+"</ul>"
		+"<p><span style=\"font-size: small;\">On the backend I am:</span></p>"
		+"<ul>"
		+"<li><span style=\"font-size: small;\">Using struts2 and tiles as my framework.</span></li>"
		+"<li><span style=\"font-size: small;\">JDO is used for persistence. I have hacked some functionality as I await google to improve their support of this spec.</span></li>"
		+"<li><span style=\"font-size: small;\">Interface to Google Picasa</span></li>"
		+"</ul>"
		+"<p><span style=\"font-size: small;\">Here is what I am working on next:</span></p>"
		+"<ul>"
		+"<li><span style=\"font-size: small;\">Persisting Site Configuration information.</span></li>"
		+"<li><span style=\"font-size: small;\">creating a sitemap view for maintaining pages.</span></li>"
		+"<li><span style=\"font-size: small;\">Using the sitemap structure to create menus on the public pages.<br /></span></li>"
		+"<li><span style=\"font-size: small;\">Creating a calendar widget for fetching events from Google Calendar.<br /></span></li>"
		+"</ul>"
		+"<p>&nbsp;</p>";
	
}